package com.anlogic.sdk.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.logging.log4j.Logger;

public class ZipUtils {
	private static Logger logger = LogUtils.getLogger(ZipUtils.class);

	public static void compress(String zipFileName, String srcPath) {
		ZipOutputStream zos = null;
		try {
			File srcFile = new File(srcPath);
			zos = new ZipOutputStream(new FileOutputStream(zipFileName));
			fileToZip(zos, srcFile, "");
	        zos.close();
		} catch (Exception e) {
			logger.error("Compress {} failed: {}", srcPath, e.getMessage());
		} finally {
			if (zos != null) {
				try {
					zos.close();
				} catch (IOException e) {
				}
			}
		}
	}
	
	public static void fileToZip(ZipOutputStream zos, File sourceFile, String parentPath) throws IOException {
        if (sourceFile.isDirectory()) {
        	parentPath = parentPath + sourceFile.getName() + File.separator;
            for (File file : sourceFile.listFiles()) {
                fileToZip(zos, file, parentPath);
            }
        } else {
            ZipEntry zipEntry = new ZipEntry(parentPath + sourceFile.getName());
            zos.putNextEntry(zipEntry);
            InputStream fileInput = new FileInputStream(sourceFile);
	        int temp = 0;
	        while((temp = fileInput.read()) != -1){
	        	zos.write(temp);
	        }
	        fileInput.close();
        }
	}

	public static void extract(String zipFileName, String destDir) {
		ZipInputStreamPatch64 zis = null;
		try {
			zis = new ZipInputStreamPatch64(new FileInputStream(zipFileName));
			ZipEntry zipEntry = null;
			while ((zipEntry = zis.getNextEntry()) != null) {
				File newFile = new File(destDir, zipEntry.getName());
				File parentDir = new File(newFile.getParent());
				if (!parentDir.exists()) {
					parentDir.mkdirs();
				}
				if (!zipEntry.isDirectory()) {
					try (FileOutputStream fos = new FileOutputStream(newFile)) {
						byte[] buffer = new byte[1024];
						int len;
						while ((len = zis.read(buffer)) > 0) {
							fos.write(buffer, 0, len);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("Extract {} failed: {}", zipFileName, e.getMessage());
		} finally {
			if (zis != null) {
				try {
					zis.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public static void extractFile(String zipFileName, String fileName, String destDir) {
		ZipFile zipFile = null;
		InputStream input = null;
		FileOutputStream output = null;
		try {		
			zipFile = new ZipFile(zipFileName);
			ZipEntry entry = zipFile.getEntry(fileName);
			input = zipFile.getInputStream(entry);
			output = new FileOutputStream(new File(destDir, fileName));
			int temp = 0;
			while ((temp = input.read()) != -1) {
				output.write(temp);
			}
		} catch (Exception e) {
			logger.error("Extract {} from {} failed: {}", fileName, zipFileName, e.getMessage());
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
				}
			}
			if (output != null) {
				try {
					output.close();
				} catch (IOException e) {
				}
			}
			if (zipFile != null) {
				try {
					zipFile.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public static String getFileBySuffix(String zipFileName, String suffix) {
		ZipInputStreamPatch64 zis = null;
		try {
			zis = new ZipInputStreamPatch64(new FileInputStream(zipFileName));
			ZipEntry entry;
			while ((entry = zis.getNextEntry()) != null) {
				String name = entry.getName();
				if (name.endsWith(suffix)) {
					return name;
				}
			}
		} catch (Exception e) {
			logger.error("Get file from {} failed: {}", zipFileName, e.getMessage());
		} finally {
			if (zis != null) {
				try {
					zis.close();
				} catch (IOException e) {
				}
			}
		}

		return null;
	}
}
